/*
 * Copyright (c) 2021 Huawei Device Co.,  Ltd.
 * Licensed under the Apache License,  Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,  software
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,  either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "fdhandler.h"

namespace SwanLink {
namespace Finance {

#define ID_MASK  (0x0000ffff)

FdHandler::FdHandler():
    m_objectId(0) {
}

FdHandler::~FdHandler()
{
    std::lock_guard<std::recursive_mutex> lock(m_mutex);
    m_mapHandle.clear();
}

void FdHandler::SetBaseId(int id)
{
    m_objectId = id << 16;
}

// 设备节点是否被打开占用
bool FdHandler::IsTakeUp(const std::string& dev)
{
    std::lock_guard<std::recursive_mutex> lock(m_mutex);
    if (m_mapHandle.find(dev) != m_mapHandle.end())
        return true;
    return false;
}

int FdHandler::GetFd(const std::string& dev)
{
    std::lock_guard<std::recursive_mutex> lock(m_mutex);
    std::unordered_map< std::string, ID_Adaptor>::const_iterator iter;
    if ((iter = m_mapHandle.find(dev)) != m_mapHandle.end()) {
        const ID_Adaptor& mapAdaptor = iter->second;
        return mapAdaptor.id;
    }
    return 0;
}


int FdHandler::AddFd(const std::string& dev, const std::shared_ptr<IAdaptor>& adaptor)
{
    std::lock_guard<std::recursive_mutex> lock(m_mutex);
    m_objectId = buildID();
    ID_Adaptor mapAdaptor;
    mapAdaptor.id = m_objectId;
    mapAdaptor.adaptor = adaptor;
    m_mapHandle[dev] = mapAdaptor;
    return m_objectId;
}

std::shared_ptr<IAdaptor>  FdHandler::GetAdaptor(int fd)
{
    std::lock_guard<std::recursive_mutex> lock(m_mutex);
    std::unordered_map<std::string, ID_Adaptor>::const_iterator iter;
    int id = fd;
    for (iter = m_mapHandle.begin(); iter != m_mapHandle.end(); ++iter) {
        const ID_Adaptor &mapAdaptor = iter->second;
        if (mapAdaptor.id == id) {
            return mapAdaptor.adaptor;
        }
    }
    return nullptr;
}

void FdHandler::DelFd(int fd)
{
    std::lock_guard<std::recursive_mutex> lock(m_mutex);
    std::unordered_map<std::string, ID_Adaptor>::iterator iter;
    int id = fd;
    for (iter = m_mapHandle.begin(); iter != m_mapHandle.end(); ++iter) {
        const ID_Adaptor &mapAdaptor = iter->second;
        if (mapAdaptor.id == id) {
            m_mapHandle.erase(iter);
            return;
        }
    }
}

int FdHandler::buildID()
{
    uint16_t objectId = m_objectId&(ID_MASK);

    std::lock_guard<std::recursive_mutex> lock(m_mutex);
    std::shared_ptr<IAdaptor> adaptor = nullptr;
    do {
        int id = m_objectId&(~ID_MASK) + (++objectId);
        adaptor = GetAdaptor(id);
    } while (adaptor != nullptr);

    m_objectId = m_objectId&(~ID_MASK) + objectId;
    return m_objectId;
}
}  // namespace Finance
}  // namespace SwanLink
